# @Version        : 1.0
# @Update Time    : 2025/8/16 20:35
# @File           : config.py
# @IDE            : PyCharm
# @Desc           : 文件描述信息
import logging
import os
from datetime import timedelta
from functools import lru_cache
from typing import Dict, List, Any, Optional

from pydantic import Field, computed_field, DirectoryPath
from pydantic_settings import BaseSettings, SettingsConfigDict

root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


class EmailConfig(BaseSettings):
    MAIL_SERVER: str = Field(default="", description="邮件服务器")
    MAIL_PORT: int = Field(default=587, description="邮件服务器端口")
    MAIL_USERNAME: str = Field(default="", description="邮件用户名")
    MAIL_PASSWORD: str = Field(default="", description="邮件密码")
    MAIL_STARTTLS: bool = Field(default=True, description="是否使用STARTTLS")
    MAIL_FROM: str = Field(default="", description="发件人邮箱")
    MAIL_SSL_TLS: bool = Field(default=False, description="是否使用SSL/TLS")


class FileUploadConfig(BaseSettings):
    """文件上传配置类"""

    # 上传文件基础路径
    STATIC_PATH: str = Field(default="static", description="静态文件基础路径")

    # FastAPI静态文件拦截路径配置
    STATIC_URL_PATH: str = Field(default="/static", description="FastAPI静态文件URL路径前缀")
    STATIC_DIRECTORY: str = Field(default="static", description="静态文件目录名称")

    # 文件上传配置
    UPLOAD_MAX_SIZE: int = Field(default=10, description="默认最大文件大小(MB)")
    UPLOAD_LARGE_FILE_MAX_SIZE: int = Field(default=100, description="大文件最大大小(MB)")
    UPLOAD_CHUNK_SIZE: int = Field(default=5, description="分片大小(MB)")
    UPLOAD_ALLOWED_EXTENSIONS: List[str] = Field(
        default=[
            ".jpg",
            ".jpeg",
            ".png",
            ".gif",
            ".webp",
            ".bmp",  # 图片
            ".pdf",
            ".doc",
            ".docx",
            ".xls",
            ".xlsx",
            ".ppt",
            ".pptx",  # 文档
            ".zip",
            ".rar",
            ".7z",  # 压缩文件
            ".mp4",
            ".avi",
            ".mov",
            ".wmv",  # 视频
            ".mp3",
            ".wav",
            ".flac",
            ".aac",  # 音频
        ],
        description="允许的文件扩展名列表",
    )
    UPLOAD_IMAGE_THUMBNAIL_SIZE: tuple = Field(default=(200, 200), description="图片缩略图尺寸")
    UPLOAD_IMAGE_QUALITY: int = Field(default=85, description="图片压缩质量")

    # 默认上传策略
    DEFAULT_UPLOAD_TYPE: str = Field(default="local", description="默认上传策略")

    # 七牛云配置（可选）
    QINIU_ACCESS_KEY: str = Field(default="", description="七牛云Access Key")
    QINIU_SECRET_KEY: str = Field(default="", description="七牛云Secret Key")
    QINIU_BUCKET_NAME: str = Field(default="", description="七牛云存储桶名称")
    QINIU_DOMAIN: str = Field(default="", description="七牛云域名")

    @computed_field
    @property
    def UPLOAD_PATH(self) -> str:
        """上传文件完整物理路径：root_path + 静态文件目录"""
        return os.path.join(root_path, self.STATIC_DIRECTORY)


class BaseConfig(EmailConfig, FileUploadConfig):
    model_config = SettingsConfigDict(
        extra="ignore",
        env_file=os.path.join(root_path, ".env"),
        env_file_encoding="utf-8",
    )

    """
    基础配置信息
    """

    BADER_PATH: str = root_path
    DEBUG: bool = Field(default=True, description="调试模式")
    # 超级管理员账号
    SUPERADMIN: str = Field(default="admin", description="超级管理员账号")

    # 系统名称
    SYSTEM_NAME: str = Field(default="Pear Admin", description="系统名称")
    # 系统描述
    SYSTEM_DESC: str = Field(
        default="Pear Admin FastAPI Backend", description="FastAPI + Tortoise ORM + Pear Admin Lay-UI"
    )
    # 系统版本
    SYSTEM_VERSION: str = Field(default="1.0.0", description="系统版本")
    # 联系人信息
    SYSTEM_CONTACT_NAME: str = Field(default="Pear Admin Team", description="系统联系人名称")
    SYSTEM_CONTACT_EMAIL: str = Field(default="admin@pearadmin.com", description="系统联系人邮箱")
    # 许可证信息
    SYSTEM_LICENSE_NAME: str = Field(default="MIT License", description="系统许可证名称")
    SYSTEM_LICENSE_URL: str = Field(default="https://opensource.org/licenses/MIT", description="系统许可证URL")
    # 服务条款
    SYSTEM_TERMS_OF_SERVICE: str = Field(default="https://www.pearadmin.com/terms", description="服务条款URL")
    SYSTEM_OPENAPI_URL: str = Field(default="/openapi.json", description="OpenAPI JSON URL")
    SYSTEM_DOCS_URL: Optional[str] = Field(default=None, description="Swagger文档URL")
    SYSTEM_REDOC_URL: Optional[str] = Field(default=None, description="ReDoc文档URL")
    SYSTEM_SERVERS: List[Dict[str, str]] = Field(
        default=[{"url": "http://localhost:8000", "description": "默认服务器"}], description="系统服务器信息"
    )

    DESENSITIZE_FIELDS: List[str] = [
        "password",
    ]

    # 主题面板的链接列表配置
    SYSTEM_PANEL_LINKS: List[Dict[str, str]] = [
        {
            "icon": "layui-icon layui-icon-auz",
            "title": "官方网站",
            "href": "http://www.pearadmin.com",
        },
        {
            "icon": "layui-icon layui-icon-auz",
            "title": "开发文档",
            "href": "http://www.pearadmin.com",
        },
        {
            "icon": "layui-icon layui-icon-auz",
            "title": "开源地址",
            "href": "https://gitee.com/Jmysy/Pear-Admin-Layui",
        },
    ]

    BASE_TEMPLATES_DIR: str = os.path.join(root_path, "templates", "build")

    # 日志文件
    LOG_PATH: str = os.path.join(root_path, "logs")

    # 上传文件配置（兼容旧版本）
    UPLOADED_PHOTOS_DEST: str = Field(default="static/upload", description="上传图片目标文件夹")
    UPLOADED_FILES_ALLOW: List[str] = Field(default=["gif", "jpg", "jpeg", "png", "webp"], description="允许的文件类型")
    UPLOADS_AUTOSERVE: bool = Field(default=True, description="是否自动提供文件服务")

    # JSON 配置
    JSON_AS_ASCII: bool = False

    # 日志配置
    LOG_EXCLUDE_PATHS: List[str] = Field(default=["/static/"], description="日志中间件需要排除的路径前缀列表")

    # 数据库的配置信息
    # MySQL(aiomysql)：mysql://user:pass@127.0.0.1:3306/pear_fastapi?charset=utf8mb4&minsize=1&maxsize=5
    # MySQL(asyncmy)：mysql+asyncmy://user:pass@127.0.0.1:3306/pear_fastapi?charset=utf8mb4&minsize=1&maxsize=5&pool_recycle=3600
    # PostgreSQL：postgres://user:pass@127.0.0.1:5432/pear_fastapi?min_size=1&max_size=5&timeout=10
    # SQLite：sqlite:///./db.sqlite3 或 sqlite://:memory:
    # Microsoft SQL Server/Oracle: sqlserver+pyodbc://user:pass@127.0.0.1:1433/pear_fastapi?driver=ODBC Driver 17 for SQL Server
    DATABASE_URI: str = Field(
        default="sqlite://:memory:",
        description="数据库连接字符串",
    )

    # 默认日志等级
    LOG_LEVEL: str = Field(default="WARNING", description="日志等级")

    # 发信设置

    # 插件配置，填写插件的文件名名称，默认不启用插件。
    PLUGIN_ENABLE_FOLDERS: List[str] = []

    # Session 设置
    PERMANENT_SESSION_LIFETIME: timedelta = timedelta(days=7)

    SESSION_TYPE: str = "filesystem"  # 默认使用文件系统来保存会话
    SESSION_PERMANENT: bool = False  # 会话是否持久化
    SESSION_USE_SIGNER: bool = True  # 是否对发送到浏览器上 session 的 cookie 值进行加密

    SECRET_KEY: str = Field(default="pearsfssfsfsd-syssdfsfsdfsdftem-flaskfsdfsfsfs", description="密钥")

    # 操作记录
    OPERATION_RECORD_METHOD: List[str] = ["POST", "PUT", "DELETE", "PATCH"]
    # 需要排除的路径
    IGNORE_OPERATION_PATH: List[str] = [
        "/system/passport/login",
    ]

    DEMO_ENV: bool = False
    # 黑名单路径
    DEMO_BLACK_LIST_PATH: List[str] = []

    # 白名单路径
    DEMO_WHITE_LIST_PATH: List[str] = [
        "/system/passport/login",
        "system.passport.logout",
        "/system/dept/data",
        "/system/power/data",
    ]

    # 数据库配置
    DB_HOST: str = "127.0.0.1"
    DB_PORT: int = 3306
    DB_USER: str = "root"
    DB_PASSWORD: str = "xxxxxx"
    DB_DATABASE: str = "pear_fastapi"
    DB_MIN_SIZE: int = 1
    DB_MAX_SIZE: int = 5
    DB_ECHO: bool = True

    @computed_field
    @property
    def MAIL_CONFIG(self) -> Dict[str, Any]:
        return {
            "MAIL_SERVER": self.MAIL_SERVER,
            "MAIL_PORT": self.MAIL_PORT,
            "MAIL_USERNAME": self.MAIL_USERNAME,
            "MAIL_PASSWORD": self.MAIL_PASSWORD,
            "MAIL_STARTTLS": self.MAIL_STARTTLS,
            "MAIL_FROM": self.MAIL_FROM,
            "MAIL_SSL_TLS": self.MAIL_SSL_TLS,
        }

    @computed_field
    @property
    def STATIC_FILES_CONFIG(self) -> Dict[str, str]:
        """静态文件配置"""
        return {
            "url_path": self.STATIC_URL_PATH,  # FastAPI拦截的URL路径
            "directory": self.STATIC_DIRECTORY,  # 静态文件目录
            "full_path": os.path.join(root_path, self.STATIC_DIRECTORY),  # 完整物理路径
        }

    @computed_field
    @property
    def TORTOISE_ORM(self) -> Dict[str, Any]:
        return {
            "connections": {
                "default": {
                    "engine": "tortoise.backends.mysql",
                    "credentials": {
                        "host": self.DB_HOST,
                        "port": self.DB_PORT,
                        "user": self.DB_USER,
                        "password": self.DB_PASSWORD,
                        "database": self.DB_DATABASE,
                        "minsize": self.DB_MIN_SIZE,
                        "maxsize": self.DB_MAX_SIZE,
                        "charset": "utf8mb4",
                        "echo": self.DB_ECHO,
                    },
                },
            },
            "apps": {
                "models": {
                    "models": ["applications.models", "aerich.models"],
                    "default_connection": "default",
                }
            },
            "use_tz": False,
            "timezone": "Asia/Shanghai",
        }


@lru_cache()
def get_settings() -> BaseConfig:
    return BaseConfig()


settings = get_settings()

TORTOISE_ORM = settings.TORTOISE_ORM
